package chat.client.service;

import chat.client.view.ClientView;
import chat.tools.ServiceTools;
import chat.tools.TimerTools;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;

/**
 * 客户端功能实现类
 *
 * @author 谈笑、
 * @dateTime 2020/10/22 19:52
 */
public class ClientCore implements Runnable {

	// 客户端窗体
	private ClientView clientView;


	// 连接时长计时器
	private TimerTools timerTools;


	// 客户端套接字
	private Socket socket;


	// 报文数据输出流
	private DataOutputStream dataOutputStream;


	// 客户端名称
	private String clientName;


	// 客户端运行状态
	private boolean isClientCoreRun = false;


	public ClientCore() {}


	// 客户端初始化成员属性
	public ClientCore(ClientView clientView, String clientName) {
		this.clientView = clientView;
		this.clientName = clientName;
	}


	/**
	 * 连接服务器
	 *
	 * #1 连接到指定IP地址和端口的服务器
	 */
	public boolean connectServer(String ip, int port) {
		try {
			// 连接到指定的服务器
			this.socket = new Socket(InetAddress.getByName(ip), port);

			// 修改客户端连接状态
			this.isClientCoreRun = true;

			// 实例化报文输出流
			this.dataOutputStream = new DataOutputStream(this.socket.getOutputStream());

			// 向服务器发送连接客户端的名称
			this.dataOutputStream.writeUTF(this.clientName);

			// 清空报文缓存
			this.dataOutputStream.flush();

			// 连接服务器成功
			return true;

		} catch (Exception e) {
			e.printStackTrace();
			// 连接服务器失败
			return false;
		}
	}


	/**
	 * 发送报文
	 *
	 * #1 将客户端输入的报文发送到服务器
	 */
	public void sengMsg(String msg) {
		try {
			// 发送报文
			this.dataOutputStream.writeUTF(msg);

			// 清空缓存
			this.dataOutputStream.flush();

		} catch (IOException e) {
			e.printStackTrace();
			this.closeClientConnect();
		}
	}


	/**
	 * 断开客户端与服务端的连接
	 */
	public void closeClientConnect() {
		if(this.dataOutputStream != null) {
			try {
				// 结束连接时长计时
				this.timerTools.setTimerToolsRun();

				// 关闭输入流
				this.dataOutputStream.close();

				// 结束客户端线程运行
				this.isClientCoreRun = false;

				// 断开客户端套接字
				if(this.socket != null) {
					this.socket.close();
				}

				// 清空在线用户列表
				clientView.getDefaultListModel().clear();

				// 添加消息记录
				this.clientView.getjTextAreas()[0].append("[系统通知 "
						+ ServiceTools.getCurrentDateTime() + "]：本端与服务器断开连接\n");

				// 修改客户端窗体样式
				ServiceTools.setStopClientWindowStyle(this.clientView);

			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}


	/**
	 * 设置客户端运行状态
	 */
	public synchronized void setClientCoreRun() {
		this.isClientCoreRun = false;
	}


	/**
	 * 设置计时器运行状态
	 */
	public void setTimerTools(TimerTools timerTools) {
		this.timerTools = timerTools;
	}


	/**
	 * 返回客户端运行状态
	 */
	public boolean getClientCoreRun() {
		return this.isClientCoreRun;
	}


	@Override
	public void run() {
		// 创建接收报文线程类
		ReceiveMsg receiveMsg = new ReceiveMsg();

		// 启动该线程
		new Thread(receiveMsg).start();
	}



	/**
	 * 接收报文线程类
	 */
	class ReceiveMsg implements Runnable {

		// 输入输如流
		private DataInputStream dataInputStream;

		public ReceiveMsg() {
			try {
				// 数据输入流
				this.dataInputStream = new DataInputStream(socket.getInputStream());
			} catch (IOException e) {
				e.printStackTrace();
				closeClientConnect();
			}
		}


		/**
		 * 分析报文数据
		 */
		public void analysisMsg(String msg) {
			// 报文数据必须大于所有定义的作用符
			if(msg.length() > 23) {

				// 所有在线客户端报文
				if("#Z_X_K_H_D#".equals(msg.substring(0, 11))) {

					// 获取到所有在线的客户端名称
					String[] allClient = msg.split("\\*K_G\\*")[1].split("\\$A_N_D\\$");

					// 清空在线用户列表
					clientView.getDefaultListModel().clear();

					// 设置列表内容
					for(String name : allClient) {
						// 添加每一个在线的客户端
						clientView.getDefaultListModel().addElement(name);
					}
					return;
				}
			}

			// 普通报文
			clientView.getjTextAreas()[0].append(msg + "\n");
		}


		@Override
		public void run() {
			try {
				// 客户端在运行才能接收报文
				while (isClientCoreRun) {
					// 接收到报文
					String msg = this.dataInputStream.readUTF();

					// 分析报文
					this.analysisMsg(msg);
				}
			} catch (IOException e) {
				// 发生异常，一般是服务端停止服务。
				e.printStackTrace();
				closeClientConnect();
			}
		}

	}

}